import THREE from './three.js';

const seg = 10;

function Arrow(){
    const height = 1000;
    const geometry = new THREE.CylinderBufferGeometry(50, 50, height, 4, seg, true);
    const position = geometry.attributes.position;
    var sizing = { halfHeight: height/2, segmentHeight: height/seg };

    const vertex = new THREE.Vector3();

    const skinIndices = [];
    const skinWeights = [];
    for ( let i = 0; i < position.count; i ++ ) {

        vertex.fromBufferAttribute( position, i );

        // compute skinIndex and skinWeight based on some configuration data

        const y = ( vertex.y + sizing.halfHeight );

        const skinIndex = Math.floor( y / sizing.segmentHeight );
        const skinWeight = ( y % sizing.segmentHeight ) / sizing.segmentHeight;

        skinIndices.push( skinIndex, skinIndex + 1, 0, 0);
        skinWeights.push( 1 - skinWeight, skinWeight, 0, 0);

    }
    geometry.setAttribute( 'skinIndex', new THREE.Uint16BufferAttribute( skinIndices, 4) );
    geometry.setAttribute( 'skinWeight', new THREE.Float32BufferAttribute( skinWeights, 4) );

    var bones = [new THREE.Bone()];
    bones[0].position.y = -sizing.halfHeight;
    for(var i = 0; i<seg; ++i){
        var bone = new THREE.Bone();
        bone.position.y = sizing.segmentHeight;
        bones[i].add(bone);
        bones.push(bone);
    }
    var material = new THREE.MeshLambertMaterial({ color: 0x888888, skinning: true, transparent: true, opacity: 0.7 });
    // var material = new THREE.MeshLambertMaterial({ color: 0x888888, skinning: true});
    const mesh = new THREE.SkinnedMesh( geometry, material );
    const skeleton = new THREE.Skeleton( bones );
    const rootBone = skeleton.bones[ 0 ];
    mesh.add( rootBone );
    mesh.bind( skeleton );
    bones[seg].scale.x = 0.01;
    bones[seg].scale.z = 0.01;
    bones[seg-1].scale.x = 3.0;
    // bones[seg-1].scale.y = 2.0;
    bones[seg-1].position.y = 0.0;
    bones[0].scale.z = 0.3;

    mesh.visible = false;
    mesh.position.y = sizing.halfHeight;
    var group = new THREE.Group();
    group.add(mesh);

    return group;
}

function shape(group, from, to , angle){
    group.children[0].visible = false;
    var now, next, tmp;
    now = new THREE.Vector3(0.0, 0.0, 0.0);
    next = new THREE.Vector3();
    tmp = new THREE.Vector3();
    tmp.copy(to);
    tmp.sub(from);
    tmp.y = 0;
    group.rotation.y = Math.atan2(tmp.x, tmp.z);
    group.position.copy(from);
    var bones = group.children[0].skeleton.bones;
    var pos = new THREE.Vector3(0, to.y-from.y, tmp.length()/bones[0].scale.z);
    var b = Math.tan(angle)*bones[0].scale.z;
    var a = (pos.y-b*pos.z)/(pos.z*pos.z);
    for (let i = 0; i < seg; i++) {
        if(bones[i+1].position.y == 0){
            continue;
        }
        var z = (i+1)*pos.z/seg;
        next.set(0, a*z*z+b*z, z);
        tmp.copy(next);
        tmp.sub(now);
        bones[i+1].position.copy(tmp);
        now.copy(next);
    }
    group.children[0].visible = true;
}

function unvisible (group){
    group.children[0].visible = false;
}

export default { Arrow, shape, unvisible };